package com.zz.study.sharding.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zz.study.sharding.algorithm.compress.DPUtil;
import com.zz.study.sharding.component.ShardHelper;
import com.zz.study.sharding.constants.Constants;
import com.zz.study.sharding.constants.DSProcessSourceEnum;
import com.zz.study.sharding.controller.form.GetLatestFFocusShipTrackReq;
import com.zz.study.sharding.controller.form.LocationForm;
import com.zz.study.sharding.entity.*;
import com.zz.study.sharding.mappers.*;
import com.zz.study.sharding.task.TrackData2RedisTask;
import com.zz.study.sharding.task.TrackDataCompressTask;
import com.zz.study.sharding.util.BeanUtil;
import com.zz.study.sharding.util.CommonUtil;
import com.zz.study.sharding.util.ConcurrentUtil;
import com.zz.study.sharding.util.GPSUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

import static com.zz.study.sharding.constants.Constants.CompressHisTrackDataTableNamePrefix;
import static com.zz.study.sharding.constants.Constants.HisTrackDataTableNamePrefix;

/**
 * created by xjx on  2023-12-28 17:48
 */
@RestController
@Api(tags = "测试")
@Slf4j
public class HifleetAisController {

    @Autowired
    private HifleetAisdataMapper hifleetAisdataMapper;

    @Autowired
    private SlaveDtFusdataFlinkMapper slaveDtFusdataFlinkMapper;

    @Autowired
    private CompressTrackDataMapper compressTrackDataMapper;

    @Autowired
    private SlaveSystemMapper slaveSystemMapper;

    @Resource(name="shipTrackQueryExecutor")
    private ThreadPoolTaskExecutor shipTrackQueryExecutor;

    @Autowired
    private TrackDataCompressTask trackDataCompressTask;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ShardHelper shardHelper;



    public static Map<String,Long> finishSyncedtableName2CountMap = new HashMap<>();

    public static long minIdTrackDataHis = 0l;

    public static final String mmsiSfix= "_MMSI";

    public static final String tarIdSfix= "_tarId";

    @Value("${algorithms.compress.dsMax}")
    private double dsMax;
    @Value("${compressed}")
    private boolean compressed;



    @PostConstruct
    public void init(){
        try{
            List<TableInfo> tableInfoList = getAllPhysicalTable(CompressHisTrackDataTableNamePrefix);

            List<TableInfo> tableInfoListNewest4Month = getNewest5Month(tableInfoList);

            for(TableInfo tableInfo:tableInfoListNewest4Month){
                log.error("表名===="+tableInfo.getTableName()+"");
                List<String> mmsiList = slaveDtFusdataFlinkMapper.distinctMMSI(tableInfo.getTableName());
                List<String> tarIdList = slaveDtFusdataFlinkMapper.distinctTarID(tableInfo.getTableName());

                log.error("mmsiList长度===="+mmsiList.size()+"");
                redisTemplate.delete(tableInfo.getTableName()+mmsiSfix);
                if(!CollectionUtils.isEmpty(mmsiList)){
                    redisTemplate.opsForList().leftPush(tableInfo.getTableName()+mmsiSfix,mmsiList);

                        List<Object> mmsiListListInRedis =  redisTemplate.opsForList().range(tableInfo.getTableName()+mmsiSfix,0,-1);
                        Object listObj =  mmsiListListInRedis.get(0);
                        List<String> mmsiList2 = CommonUtil.objToList(listObj);
                    log.error("表名===="+tableInfo.getTableName()+"mmsiList2====长度===="+mmsiList2.size()+"");
                }
                if(!CollectionUtils.isEmpty(tarIdList)){
                    redisTemplate.opsForList().leftPush(tableInfo.getTableName()+tarIdSfix,tarIdList);

                    List<Object> tarIdListListInRedis =  redisTemplate.opsForList().range(tableInfo.getTableName()+tarIdSfix,0,-1);
                    Object listObj =  tarIdListListInRedis.get(0);
                    List<String> tarIdList2 = CommonUtil.objToList(listObj);
                    log.error("表名===="+tableInfo.getTableName()+"tarIdList2====长度===="+tarIdList2.size()+"");
                }

            }
            log.error("添加结束");
        }catch (Exception e){
            log.error("初始化缓存失败====="+e.getMessage());
        }

    }

    public List<TableInfo> getNewest5Month(List<TableInfo> tableInfoList){
        List<TableInfo> newest5MonthTableInfo = new ArrayList<>();

        List<String> newest5Month = new ArrayList<>();
        Date now = new Date();
        String currentTableName = shardHelper.getShardTableName(CompressHisTrackDataTableNamePrefix,now);
        newest5Month.add(currentTableName);

        Date oneMonthAgo = DateUtil.offsetMonth(now,-1);
        String oneMonthAgoTableName = shardHelper.getShardTableName(CompressHisTrackDataTableNamePrefix,oneMonthAgo);
        newest5Month.add(oneMonthAgoTableName);

        Date twoMonthAgo = DateUtil.offsetMonth(now,-2);
        String twoMonthAgoTableName = shardHelper.getShardTableName(CompressHisTrackDataTableNamePrefix,twoMonthAgo);
        newest5Month.add(twoMonthAgoTableName);

        Date threeMonthAgo = DateUtil.offsetMonth(now,-3);
        String threeMonthAgoTableName = shardHelper.getShardTableName(CompressHisTrackDataTableNamePrefix,threeMonthAgo);
        newest5Month.add(threeMonthAgoTableName);

        Date fourMonthAgo = DateUtil.offsetMonth(now,-4);
        String fourMonthAgoTableName = shardHelper.getShardTableName(CompressHisTrackDataTableNamePrefix,fourMonthAgo);
        newest5Month.add(fourMonthAgoTableName);

        for(TableInfo tableInfo:tableInfoList){
            if(newest5Month.contains(tableInfo.getTableName())){
                newest5MonthTableInfo.add(tableInfo);
            }
        }

        return newest5MonthTableInfo;


    }

    @GetMapping("/testMapObject")
    @ApiOperation("测试mapObject")
    public String testMapObject() {
        List<Map<String,Object>> dataListNew = new ArrayList<>();
        List<Map<String,Object>> dataList = new ArrayList<>();
        Map<String,List<Map<String,Object>>> map = new HashMap<>();
        try {
            List<String> tarIdList = new ArrayList<>();
            tarIdList.add("23303893");
           Date startTime =  DateUtil.parse("2024-03-04 03:01:00","yyyy-MM-dd HH:mm:ss");
            Date endTime =  DateUtil.parse("2024-03-04 04:26:00","yyyy-MM-dd HH:mm:ss");
            dataList =   slaveDtFusdataFlinkMapper.getTrackMapByTarIdListAndTime(tarIdList,startTime,endTime);
            log.error("根据tarId获取数据====="+dataList.size());
            dataListNew.add(dataList.get(0));
            dataListNew.add(dataList.get(dataList.size()-1));
            log.error("map的长度====="+map.size());
        }catch (Exception e){
            log.error("并发根据tarId获取轨迹错误======="+e.getMessage());
        }
        return JSON.toJSONString(dataListNew);
    }


    @GetMapping("/createTrack")
    public String createTrack() {

        HifleetAisdata hifleetAisdata = new HifleetAisdata();
        hifleetAisdata.setId(12344852L);
        hifleetAisdata.setMmsi("413378580");
        hifleetAisdata.setStatus("机动船在航");
        hifleetAisdata.setTurnrate("0.0");
        hifleetAisdata.setSpeed(9.4d);
        hifleetAisdata.setLon(123.62955666666667d);
        hifleetAisdata.setLat(25.38876d);
        hifleetAisdata.setCourse(330d);
        hifleetAisdata.setHeading(251d);
        hifleetAisdata.setImonumber(0);
        hifleetAisdata.setCallsign("BNSC");
        hifleetAisdata.setName("CHINACOASTGUARD1302");
        hifleetAisdata.setCnName("");
        hifleetAisdata.setEta("2023-03-23 06:00:00");
        hifleetAisdata.setType("工程及服务船");
        hifleetAisdata.setMinotype("执法船");
        hifleetAisdata.setUpdatetime(new Date());
        hifleetAisdata.setCreateTime(DateUtil.parse("2023-9-26 21:27:06","yyyy-MM-dd HH:mm:ss"));
        hifleetAisdataMapper.addRecord(hifleetAisdata);
        return "success";
    }

    @GetMapping("/createData")
    public String createData() {

        DtFusdataFlink hifleetAisdata = new DtFusdataFlink();
        hifleetAisdata.setId(12344853L);
        hifleetAisdata.setLength(23);
        hifleetAisdata.setMmsi(413378580);
        hifleetAisdata.setTarID(467834567L);
        hifleetAisdata.setRadarType(0);
        hifleetAisdata.setAISType(1);
        hifleetAisdata.setBeidouType(1);
        hifleetAisdata.setSourceNames("BXDRE");
        hifleetAisdata.setTerminalID("45436356");
        hifleetAisdata.setState(0);
        hifleetAisdata.setUid("546546");
        hifleetAisdata.setArchiveTime(cn.hutool.core.date.DateUtil.parse("2023-10-26 21:27:06","yyyy-MM-dd HH:mm:ss"));
        hifleetAisdata.setSpeed(9.4f);
        hifleetAisdata.setLon(123.62955667d);
        hifleetAisdata.setLat(25.38876d);
        hifleetAisdata.setCourse(330f);
        hifleetAisdata.setHeading(251f);
        hifleetAisdata.setAISName("COAST1302");
        hifleetAisdata.setVesselType(9);
        hifleetAisdata.setRecordTime(cn.hutool.core.date.DateUtil.parse("2023-10-26 21:27:06","yyyy-MM-dd HH:mm:ss"));
        slaveDtFusdataFlinkMapper.insertDtFusdataFlink(hifleetAisdata);


        DtFusdataFlink hifleetAisdata2 = new DtFusdataFlink();
        hifleetAisdata2.setId(12345852L);
        hifleetAisdata2.setLength(23);
        hifleetAisdata2.setMmsi(413378580);
        hifleetAisdata2.setTarID(467834567L);
        hifleetAisdata2.setRadarType(0);
        hifleetAisdata2.setAISType(1);
        hifleetAisdata2.setBeidouType(1);
        hifleetAisdata2.setSourceNames("BXDRE");
        hifleetAisdata2.setTerminalID("45436356");
        hifleetAisdata2.setState(0);
        hifleetAisdata2.setUid("546546");
        hifleetAisdata2.setArchiveTime(cn.hutool.core.date.DateUtil.parse("2023-11-26 21:27:06","yyyy-MM-dd HH:mm:ss"));
        hifleetAisdata2.setSpeed(9.4f);
        hifleetAisdata2.setLon(123.62955667d);
        hifleetAisdata2.setLat(25.38876d);
        hifleetAisdata2.setCourse(330f);
        hifleetAisdata2.setHeading(251f);
        hifleetAisdata2.setAISName("COAST1302");
        hifleetAisdata2.setVesselType(9);
        hifleetAisdata2.setRecordTime(cn.hutool.core.date.DateUtil.parse("2023-11-26 21:27:06","yyyy-MM-dd HH:mm:ss"));
        slaveDtFusdataFlinkMapper.insertDtFusdataFlink(hifleetAisdata2);
        return "success";
    }





    @GetMapping("/getMinMaxInfo")
    @ApiOperation("获取最大最小值")
    @ResponseBody
    public Map<String,Object> getMinMaxInfo() {
        long start =System.currentTimeMillis();
        Map<String,Object> returnMap = new HashMap<>();
        List<TableInfo>  tableInfoList =    getAllPhysicalTable(HisTrackDataTableNamePrefix);
        long minId =0l;
        if(minIdTrackDataHis<=0){
            log.error("获取表的总数==="+tableInfoList.size());
            minId =  slaveSystemMapper.getMinIdByTableName(tableInfoList.get(0).getTableName());
            minIdTrackDataHis = minId;
        }else{
            minId = minIdTrackDataHis;
        }

        returnMap.put("min",minId);
        int zeroCountIndex = 0;
        for(int i=0;i<tableInfoList.size();i++){
            if(!finishSyncedtableName2CountMap.containsKey(tableInfoList.get(i).getTableName())){
                long count =  slaveSystemMapper.getCountByTableName(tableInfoList.get(i).getTableName());
                finishSyncedtableName2CountMap.put(tableInfoList.get(i).getTableName(),count);
                if(count==0){
                    zeroCountIndex = i;
                    finishSyncedtableName2CountMap.remove(tableInfoList.get(zeroCountIndex).getTableName());
                    break;
                }
            }
        }
        long maxId =  slaveSystemMapper.getMaxIdByTableName(tableInfoList.get(zeroCountIndex-1).getTableName());
        returnMap.put("max",maxId);
        log.error("获取最大最小值耗时====="+(System.currentTimeMillis()-start)+"ms");
        return returnMap;
    }
    @GetMapping("/getHisRecordsCountByRange")
    @ApiOperation("获取min,max范围记录总数222222222")
    @ResponseBody
    public Long getHisRecordsCountByRange(@RequestParam("min") long min,@RequestParam("max") long max) {
        long start = System.currentTimeMillis();
        Long count =    slaveDtFusdataFlinkMapper.getHisRecordsCountByRange(min,max);
        log.error("获获取min,max范围记录总数耗时====="+(System.currentTimeMillis()-start)+"ms");
        return count;
    }




    @PostMapping("/getDistance")
    @ApiOperation("获取经纬度之间的距离")
    @ResponseBody
    public double getDistance(@RequestBody LocationForm form){
        return GPSUtil.getDistance(form.getLongitude1(),form.getLatitude1(),form.getLongitude2(),form.getLatitude2());
    }



    @GetMapping("/getCompressData")
    @ApiOperation("获取压缩后的轨迹数据")
    @ResponseBody
    public List<DtFusdataFlinkSimple> getCompressData(@RequestParam("tarId") Long tarId,
                                              @RequestParam("dsMax") Double dsMax,
                                              @RequestParam("startTime") String startTime,
                                              @RequestParam("endTime") String endTime) {
        Map<String,Object> map = new HashMap<>();
        Date startTimeObj = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss");
        Date endTimeObj = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss");
        long start = System.currentTimeMillis();

        List<DtFusdataFlinkSimple> dataListTotal = new ArrayList<>();
        List<String > tableNameList =  com.zz.study.sharding.util.DateUtil.getTableListByTimeRange(CompressHisTrackDataTableNamePrefix,startTimeObj,endTimeObj);
        List<String> tableNameListAllPhysical =  getAllPhysicalTableNameList(CompressHisTrackDataTableNamePrefix);

        for(String tableName:tableNameList){
            if(tableNameListAllPhysical.contains(tableName)){
                List<DtFusdataFlinkSimple> dataList =    compressTrackDataMapper.getCompressTrackByMMSIAndTimeSimpleSingle(tableName,tarId.toString(),startTimeObj,endTimeObj);
                if(!CollectionUtils.isEmpty(dataList)){
                    dataListTotal.addAll(dataList);
                }
            }
        }
        if(!CollectionUtils.isEmpty(dataListTotal)){
            List<DtFusdataFlinkSimple> afterCompressedList =  DPUtil.dpAlgorithmSimple(dataListTotal,dsMax);


            Collections.sort(afterCompressedList, new Comparator<DtFusdataFlinkSimple>() {
                @Override
                public int compare(DtFusdataFlinkSimple o1, DtFusdataFlinkSimple o2) {
                    return ((o1.getRecordTime().getTime()-o2.getRecordTime().getTime())>0?1:-1);
                }
            });

            return afterCompressedList;
        }


        return new ArrayList<>();

    }



    @GetMapping("/getUnCompressData")
    @ApiOperation("获取没有压缩过的轨迹数据")
    @ResponseBody
    public List<DtFusdataFlinkSimple> getUnCompressData(@RequestParam("tarId") Long tarId,
                                              @RequestParam("startTime") String startTime,
                                @RequestParam("endTime") String endTime) {
        Map<String,Object> map = new HashMap<>();
        Date startTimeObj = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss");
        Date endTimeObj = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss");
        long start = System.currentTimeMillis();
        List<DtFusdataFlinkSimple> dataListTotal = new ArrayList<>();
        List<String > tableNameList =  com.zz.study.sharding.util.DateUtil.getTableListByTimeRange(HisTrackDataTableNamePrefix,startTimeObj,endTimeObj);
        List<String> tableNameListAllPhysical =  getAllPhysicalTableNameList(HisTrackDataTableNamePrefix);
        for(String tableName:tableNameList){
            if(tableNameListAllPhysical.contains(tableName)){
                List<DtFusdataFlinkSimple> dataList =    slaveDtFusdataFlinkMapper.getTrackByMMSIAndTimeSimpleSingle(tableName,tarId.toString(),startTimeObj,endTimeObj);
                if(!CollectionUtils.isEmpty(dataList)){
                    dataListTotal.addAll(dataList);
                }
            }
        }
        if(!CollectionUtils.isEmpty(dataListTotal)){
            Collections.sort(dataListTotal, new Comparator<DtFusdataFlinkSimple>() {
                @Override
                public int compare(DtFusdataFlinkSimple o1, DtFusdataFlinkSimple o2) {
                    return ((o1.getRecordTime().getTime()-o2.getRecordTime().getTime())>0?1:-1);
                }
            });

        }
        return dataListTotal;
    }

    public List<String> distinctPoint(List<DtFusdataFlink> points){
        Set<String> pointList = new HashSet<>();
        for(DtFusdataFlink data:points){
           pointList.add(data.getLon()+","+data.getLat());
        }
        return new ArrayList<>(pointList);
    }


    @GetMapping("/getHisRecordsByRange")
    @ApiOperation("获取min,max范围记录总数")
    @ResponseBody
    public List<Map<String,Object>> getHisRecordsByRange(@RequestParam("min") long min,@RequestParam("max") long max) {
        long start = System.currentTimeMillis();
        List<Map<String,Object>> list =    slaveDtFusdataFlinkMapper.getHisRecordsByRange(min,max);
        log.error("获获取min,max范围记录总数耗时====="+(System.currentTimeMillis()-start)+"ms");
        return list;
    }


    @GetMapping("/writeCompresseData")
    @ApiOperation("写压缩数据到新表")
    @ResponseBody
    public String writeCompresseData() {
        trackDataCompressTask.lastWeekTrackDataCompress();
        return "success";
    }

    @GetMapping("/triggerScheduleTask")
    @ApiOperation("触发周期写数据")
    @ResponseBody
    public String scheduleCompressTrackdata() {
        trackDataCompressTask.scheduleCompressTrackdata();
        return "success";
    }

    @GetMapping("/writeCompresseDataRange")
    @ApiOperation("按照时间范围写压缩数据到新表")
    @ResponseBody
    public String writeCompresseDataRange(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) {
        trackDataCompressTask.writeCompressDataByDateRange(startTime,endTime);
        return "success";
    }

    @GetMapping("/getHisRecordsCount")
    @ApiOperation("获取记录总数")
    @ResponseBody
    public Long getHisRecordsCount() {
        long start =System.currentTimeMillis();
        List<TableInfo>  tableInfoList =    getAllPhysicalTable(HisTrackDataTableNamePrefix);
        int zeroCountIndex = 0;
        for(int i=0;i<tableInfoList.size();i++){
            if(!finishSyncedtableName2CountMap.containsKey(tableInfoList.get(i).getTableName())){
                long count =  slaveSystemMapper.getCountByTableName(tableInfoList.get(i).getTableName());
                finishSyncedtableName2CountMap.put(tableInfoList.get(i).getTableName(),count);
                if(count==0){
                    zeroCountIndex = i;
                    finishSyncedtableName2CountMap.remove(tableInfoList.get(zeroCountIndex).getTableName());
                    break;
                }
            }
        }
        Long totalCount = 0l;
        for(TableInfo tableInfo:tableInfoList){
            if(!finishSyncedtableName2CountMap.containsKey(tableInfo.getTableName())){
                long count =  slaveSystemMapper.getCountByTableName(tableInfo.getTableName());
                totalCount = totalCount+count;
            }else{
                totalCount =totalCount +finishSyncedtableName2CountMap.get(tableInfo.getTableName());
            }
        }


       // Long count =    slaveDtFusdataFlinkMapper.getHisRecordsCount();
        System.out.println("count====="+(totalCount));
        log.error("获取记录总数耗时====="+(System.currentTimeMillis()-start)+"ms");
        return totalCount;
    }

    public List<String> getAllPhysicalTableNameList(String tableNamePrefix){
        List<String> returnList = new ArrayList<>();
        List<TableInfo>  tableInfoList =  getAllPhysicalTable(tableNamePrefix);
        if(!CollectionUtils.isEmpty(tableInfoList)){
            for (TableInfo tableInfo:tableInfoList){
                returnList.add(tableInfo.getTableName());
            }

        }
        return returnList;
    }

    public List<TableInfo> getAllPhysicalTable(String tableNamePrefix){
        List<TableInfo>  tableInfoList =    slaveSystemMapper.queryTableInfoByName(tableNamePrefix);
        tableInfoList.sort(new Comparator<TableInfo>() {
            @Override
            public int compare(TableInfo o1, TableInfo o2) {
                String tableName1 = o1.getTableName();
                String tableName2 = o2.getTableName();
                int prefixSufixIndex = tableNamePrefix.length();
                String year1 = tableName1.substring(prefixSufixIndex,prefixSufixIndex+4);
                String month1 = tableName1.substring(prefixSufixIndex+4,tableName1.length());
                String year2 = tableName2.substring(prefixSufixIndex,prefixSufixIndex+4);
                String month2 = tableName2.substring(prefixSufixIndex+4,tableName2.length());
                Integer number1 = Integer.valueOf(year1) * 100 +  Integer.valueOf(month1);
                Integer number2 = Integer.valueOf(year2) * 100 +  Integer.valueOf(month2);

                return number1-number2;
            }
        });
        return tableInfoList;
    }


    @GetMapping("/tableExists")
    @ApiOperation("tableName表是否存在")
    @ResponseBody
    public boolean tableExists(@RequestParam("tableName") String tableName) {
        long start =System.currentTimeMillis();
        List<TableInfo>  tableInfoList =    slaveSystemMapper.queryTableInfoByName(tableName);
        log.error("tableName表是否存在耗时====="+(System.currentTimeMillis()-start)+"ms");
       if(!CollectionUtils.isEmpty(tableInfoList)){
           return true;
       }
        return false;
    }

    @GetMapping("/getHisRangeDateRecords")
    @ApiOperation("获取所有startTime，endTime范围的数据")
    @ResponseBody
    public List<DtFusdataFlink> getHisRangeDateRecords(
            @RequestParam("startTime") String startTime,
            @RequestParam("endTime") String endTime) {
        long start =System.currentTimeMillis();
        Date startTimeObj = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss");
        Date endTimeObj = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss");
        List<DtFusdataFlink>  beanList =    slaveDtFusdataFlinkMapper.getHisRangeDateRecords(startTimeObj,endTimeObj);
        log.error("获取所有startTime，endTime范围的数据耗时====="+(System.currentTimeMillis()-start)+"ms");
        return beanList;
    }

    @GetMapping("/getHisRangeDateRecordsSimple")
    @ApiOperation("获取所有startTime，endTime范围的数据simple")
    @ResponseBody
    public List<DtFusdataFlinkSimple> getHisRangeDateRecordsSimple(
            @RequestParam("startTime") String startTime,
            @RequestParam("endTime") String endTime) {
        long start = System.currentTimeMillis();
        Date startTimeObj = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss");
        Date endTimeObj = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss");
        List<DtFusdataFlinkSimple>  beanList =    slaveDtFusdataFlinkMapper.getHisRangeDateRecordsSimple(startTimeObj,endTimeObj);
        log.error("获取所有startTime，endTime范围的数据simple耗时====="+(System.currentTimeMillis()-start)+"ms");
        return beanList;
    }

    /**
     * 540
     * @param mmsi
     * @param startTime
     * @param endTime
     * @return
     */
    @GetMapping("/getTrackByMMSIAndTime")
    @ApiOperation("根据mmsi获取所有startTime，endTime范围的数据")
    @ResponseBody
    public List<DtFusdataFlinkSimple> getTrackByMMSIAndTime(
            @RequestParam("mmsi") String mmsi,
            @RequestParam("startTime") String startTime,
            @RequestParam("endTime") String endTime) {
        long start =System.currentTimeMillis();
        Date now = new Date();
        Date startTimeObj = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss");
        Date endTimeObj = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss");
        try{
            if(DateUtil.between(startTimeObj,now, DateUnit.HOUR)<72){
                log.error("时间差小于3天=====");
                List<DtFusdataFlinkSimple>  beanList =    slaveDtFusdataFlinkMapper.getTrackByMMSIAndTimeSimpleSingle("dt_fusdata_flink",mmsi,startTimeObj,endTimeObj);
                List<DtFusdataFlinkSimple> afterCompressList =  DPUtil.dpAlgorithmSimple(beanList,dsMax);
                afterCompressList.sort(Comparator.comparing(DtFusdataFlinkSimple::getRecordTime));
                log.error("根据mmsi获取所有startTime，endTime范围的数据simple耗时====="+(System.currentTimeMillis()-start)+"ms");
                return afterCompressList;
            }
            List<DtFusdataFlinkSimple>  beanList =    compressTrackDataMapper.getCompressTrackByMMSIAndTimeSimple(mmsi,startTimeObj,endTimeObj);
            log.error("获取压缩轨迹分表长度===="+beanList.size());
            if(CollectionUtils.isEmpty(beanList)){
                return new ArrayList<>();
            }
            log.error("根据mmsi获取压缩轨迹分表所有startTime，endTime范围的数据simple耗时====="+(System.currentTimeMillis()-start)+"ms");
            return beanList;
        }catch (Exception e){
            log.error("获取轨迹分表出错===="+e.getMessage());
        }

        return new ArrayList<>();
    }

    @GetMapping("/removeKey")
    @ApiOperation("删除缓存按照key")
    @ResponseBody
    public String removeKey(
            @RequestParam("key") String key) {
        redisTemplate.delete(key);
        return "success";
    }


    @GetMapping("/getByKey")
    @ApiOperation("根据key获取缓存的数据  字段名称=字段值")
    @ResponseBody
    public String getByKey(
            @RequestParam("key") String key) {
       List<Object> objectList =  redisTemplate.opsForList().range(key,0,-1);
       if(CollectionUtils.isEmpty(objectList)){
           return "";
       }
        return JSON.toJSONString(objectList);
    }


    /**
     * 476行
     * @param mmsi
     * @param startTime
     * @param endTime
     * @return
     */
    @GetMapping("/getTrackByMMSIAndTimeRedis")
    @ApiOperation("根据mmsi获取所有startTime，endTime范围的数据redis")
    @ResponseBody
    public List<DtFusdataFlinkSimple> getTrackByMMSIAndTimeRedis(
            @RequestParam("mmsi") String mmsi,
            @RequestParam("startTime") String startTime,
            @RequestParam("endTime") String endTime) {
        long start =System.currentTimeMillis();
        Date startTimeObj = DateUtil.parse(startTime,"yyyy-MM-dd HH:mm:ss");
        Date endTimeObj = DateUtil.parse(endTime,"yyyy-MM-dd HH:mm:ss");
        log.error("判断在redis中是否存在============");
       if(redisContains(mmsi)){
           log.error("在redis中存在============");
           List<DtFusdataFlinkSimple> listRedis =  redisFetch(mmsi);
           log.error("根据mmsi获取所有startTime，endTime范围的数据redissimple耗时====="+(System.currentTimeMillis()-start)+"ms");
           return listRedis;
       }
        log.error("在redis中不存在============");
       // List<DtFusdataFlinkSimple>  beanList =    slaveDtFusdataFlinkMapper.getTrackByMMSIAndTimeSimple(mmsi,startTimeObj,endTimeObj);
       // log.error("根据mmsi获取所有startTime，endTime范围的数据simple耗时====="+(System.currentTimeMillis()-start)+"ms");
        log.error("写入数据到redis============");
        List<DtFusdataFlinkSimple> allList=   put2Redis(mmsi,startTimeObj,endTimeObj);
        log.error("根据mmsi获取所有startTime，endTime范围的数据redissimple耗时====="+(System.currentTimeMillis()-start)+"ms");
        return allList;
    }

    public boolean redisContains(String mmsi){
        List<TableInfo> tableInfoList =  getAllPhysicalTable(HisTrackDataTableNamePrefix);
        for(TableInfo tableInfo:tableInfoList){
            String tableName = tableInfo.getTableName();
            Boolean exist =  redisTemplate.hasKey(getKey(tableName,mmsi));
            if(exist){
               return true;
            }
        }
        return  false;
    }

    public static String getKey(String tableName,String mmsi){
        return mmsi+"_"+tableName;
    }

    public List<DtFusdataFlinkSimple> put2Redis(String mmsi,Date startTimeObj,Date endTimeObj){
        log.error("判断该mmsi在哪些表存在====start=====");
        long start =System.currentTimeMillis();
        List<String> tableInfoList =  getExistDataTableNameList(mmsi);
        log.error("判断该mmsi在哪些表存在====end耗时====="+(System.currentTimeMillis()-start)+"ms");
        log.error("该目标id在这些表中存在数据======"+tableInfoList.get(0));
        List<DtFusdataFlinkSimple> allList = new ArrayList<>();
        for(String str:tableInfoList){
            log.error("从starRocks数据库中获取数据======");
            List<DtFusdataFlinkSimple>  beanList =    slaveDtFusdataFlinkMapper.getTrackByMMSIAndTimeSimpleSingle(str,mmsi,startTimeObj,endTimeObj);
            allList.addAll(beanList);
            log.error("从starRocks数据库中获取数据完成，并且写入到redis数据库中======"+beanList.size());
            ConcurrentUtil.doJob(shipTrackQueryExecutor, new TrackData2RedisTask(redisTemplate,beanList,str,mmsi));
        }
        return  allList;
    }

    /**
     * 因为有些mmsi在某些表不存在，但是查询的时候还是会耗时很多时间,找出对应的在哪几张表里
     * @return
     */
    public List<String> getExistDataTableNameList(String mmsi){
        Set<String> returnList = new HashSet<>();
        try{
            List<TableInfo> tableInfoList =  getAllPhysicalTable(HisTrackDataTableNamePrefix);
            for(TableInfo tableInfo:tableInfoList){
                List<Object> mmsivalueList = redisTemplate.opsForList().range(tableInfo.getTableName()+mmsiSfix,0,-1);

                List<Object> tarIdvalueList = redisTemplate.opsForList().range(tableInfo.getTableName()+tarIdSfix,0,-1);

                if(!CollectionUtils.isEmpty(mmsivalueList)){
                    List<String> mmsiListInCache = CommonUtil.objToList(mmsivalueList.get(0));
                    if(mmsiListInCache.contains(mmsi)){
                        log.error("该mmsi===="+mmsi+"在mmsiredis中存在");
                        returnList.add(tableInfo.getTableName());
                    }
                }

                if(!CollectionUtils.isEmpty(tarIdvalueList)){
                    List<String> tarIdListInCache = CommonUtil.objToList(tarIdvalueList.get(0));
                    if(tarIdListInCache.contains(mmsi)){
                        log.error("该mmsi===="+mmsi+"在taridredis中存在");
                        returnList.add(tableInfo.getTableName());
                    }
                }

//                List<DtFusdataFlinkSimple> dataList =  slaveDtFusdataFlinkMapper.getTrackByMMSISimpleSingle(tableInfo.getTableName(),mmsi);
//                if(!CollectionUtils.isEmpty(dataList)){
//                    returnList.add(tableInfo.getTableName());
//                }
//            List<Object> valueList2 = redisTemplate.opsForList().range(tableInfo.getTableName()+tarIdSfix,0,-1);
//            if(valueList2.contains(mmsi)){
//                returnList.add(tableInfo.getTableName());
//            }


            }
        }catch (Exception e){
            log.error(e.getMessage());
        }


        return new ArrayList<>(returnList);
    }

    public List<DtFusdataFlinkSimple> redisFetch(String mmsi){
        List<DtFusdataFlinkSimple> allList = new ArrayList<>();
        try{
            List<TableInfo> tableInfoList =  getAllPhysicalTable(CompressHisTrackDataTableNamePrefix);
            for(TableInfo tableInfo:tableInfoList){
                String tableName = tableInfo.getTableName();
                List<Object> beanList =  redisTemplate.opsForList().range(getKey(tableName,mmsi),0,-1);
                if(!CollectionUtils.isEmpty(beanList)){
                    for(Object listObj:beanList){
                        List<DtFusdataFlinkSimple> tempList = CommonUtil.objToListTrackdata(listObj);
                        if(!CollectionUtils.isEmpty(tempList)){
                            allList.addAll(tempList);
                        }
                    }
                }
//                List<DtFusdataFlinkSimple> tempList = new ArrayList<>();
//                for(Object obj:beanList){
//                    DtFusdataFlinkSimple bean = new ObjectMapper().convertValue(obj, DtFusdataFlinkSimple.class);
//                    tempList.add(bean);
//                }

            }
        }catch (Exception e){
            log.error("从redis获取数据报错==="+e.getMessage());
        }


        return  allList;
    }



    @GetMapping("/list")
    public String list() {
        long start = System.currentTimeMillis();
        Date startTime = DateUtil.parse("2023-09-20 00:00:00","yyyy-MM-dd HH:mm:ss");
        Date endTime = DateUtil.parse("2023-10-02 00:00:00","yyyy-MM-dd HH:mm:ss");
        List<HifleetAisdata> list =    hifleetAisdataMapper.getListwithPageInfo(new HifleetAisdata(),startTime,endTime,0,10);
        System.out.println("分表查询耗时====="+(System.currentTimeMillis()-start)+"ms");
        return JSON.toJSONString(list);
    }

    /**
     * 根据
     * @return
     */
    @GetMapping("/getTargetTable")
    @ApiOperation("根据时间获取表名")
    public String getTargetTable(@RequestParam("time") String time) {
        Date date = new Date(DateUtil.parseDateTime(time).getTime());
        String targetTableName = com.zz.study.sharding.util.DateUtil.getShardTableName(HisTrackDataTableNamePrefix,date);
        return targetTableName;
    }


    @PostMapping("/getLatestFocusShipTrack")
    @ApiOperation("根据mmsi获取所有startTime，endTime范围的数据redis")
    @ResponseBody
    public Map<String,List<DtFusdataFlinkSimple>> getLatestFocusShipTrack(@RequestBody GetLatestFFocusShipTrackReq req){
        return focusShipLatestDataRedisFetch(req);
    }

    public Map<String,List<DtFusdataFlinkSimple>>  focusShipLatestDataRedisFetch(GetLatestFFocusShipTrackReq req){

        Map<String,List<DtFusdataFlinkSimple>> totalMap  = new HashMap<>();
        Date endTimeObj = new Date();
        Date startTimeObj = DateUtil.offsetMinute(endTimeObj,-60);

        for(DatastreamProcess datastreamProcess:req.getDatastreamProcessList()){
            String key = datastreamProcess.getFilterFieldName()+datastreamProcess.getOperator()+datastreamProcess.getFieldExpectValue();
            log.error("key======="+key);
            List<Object> trackDataListInRedis =  redisTemplate.opsForList().range(key,0,-1);

            try {
                List<Map<String,Object>> trackDataList = CommonUtil.objToMapListTrackdata(trackDataListInRedis);
                log.error("根据key获取到的数据======="+JSON.toJSONString(trackDataList));
                if(CollectionUtils.isEmpty(trackDataList)){
                    log.error("从数据库查询======getTrackByMMSIAndTimeSimple====="+datastreamProcess.getFieldExpectValue());
                    List<DtFusdataFlinkSimple>  beanList =    slaveDtFusdataFlinkMapper.getTrackByMMSIAndTimeSimple(datastreamProcess.getFieldExpectValue(),startTimeObj,endTimeObj);
                    if(!CollectionUtils.isEmpty(beanList)){
                        totalMap.put(datastreamProcess.getFieldExpectValue(),beanList);
                        for(DtFusdataFlinkSimple track:beanList){
                            redisTemplate.opsForList().leftPush(key,track);
                        }
                    }
                }else{
                    List<DtFusdataFlinkSimple>  beanList =   BeanUtil.copyProperties(trackDataList,DtFusdataFlinkSimple.class);
                    totalMap.put(datastreamProcess.getFieldExpectValue(),beanList);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return  totalMap;
    }



}
